#include "BoundaryConditions.h"
#include <nlohmann/json.hpp>
#include "Function.h"
#include <cmath>

using json = nlohmann::json;

// 构造函数
BoundaryConditions::BoundaryConditions(const std::string& filename) {
    loadFromJson(filename);
}

void BoundaryConditions::loadFromJson(const std::string& filename) {
    // 读取 JSON 文件
    std::ifstream inputFile(filename);
    json config;
    inputFile >> config;

    // 解析输入参数
    type = config["boundary_conditions"]["type"];
    dimension = config["grid"]["dimension"];

    std::function<double(double)> boundary_x_left_1D;
    std::function<double(double)> boundary_x_right_1D;
    std::function<double(double, double)> boundary_x_left_2D;
    std::function<double(double, double)> boundary_x_right_2D;
    std::function<double(double, double)> boundary_y_up_2D;
    std::function<double(double, double)> boundary_y_down_2D;

    if (dimension == 1) {
        std::string boundary_condition_x_left = config["functions"]["boundary_condition_x_left"];
        std::string boundary_condition_x_right = config["functions"]["boundary_condition_x_right"];
        
        // 解析一维表达式
        boundary_x_left_1D = parseExpression_1D(boundary_condition_x_left);
        boundary_x_right_1D = parseExpression_1D(boundary_condition_x_right);
        
        conditions_1D.push_back(boundary_x_left_1D);
        conditions_1D.push_back(boundary_x_right_1D);
    }
    else if (dimension == 2) {
        std::string boundary_condition_x_left = config["functions"]["boundary_condition_x_left"];
        std::string boundary_condition_x_right = config["functions"]["boundary_condition_x_right"];
        std::string boundary_condition_y_up = config["functions"]["boundary_condition_y_up"];
        std::string boundary_condition_y_down = config["functions"]["boundary_condition_y_down"];
        
        // 解析二维表达式
        boundary_x_left_2D = parseExpression_2D(boundary_condition_x_left);
        boundary_x_right_2D = parseExpression_2D(boundary_condition_x_right);
        boundary_y_up_2D = parseExpression_2D(boundary_condition_y_up);
        boundary_y_down_2D = parseExpression_2D(boundary_condition_y_down);

        conditions_2D.push_back(boundary_x_left_2D);
        conditions_2D.push_back(boundary_x_right_2D);
        conditions_2D.push_back(boundary_y_up_2D);
        conditions_2D.push_back(boundary_y_down_2D);
    }
}

// 获取边界条件类型
std::string BoundaryConditions::getType() const {
    return type;
}

// 获取某个边界条件值
double BoundaryConditions::getCondition_1D(double x, size_t index) const {
    if (index >= conditions_1D.size()) {
        throw std::out_of_range("Index exceeds the number of available boundary conditions");
    }
    return conditions_1D[index](x);
}

// 获取某个边界条件值
double BoundaryConditions::getCondition_2D(double x, double y, size_t index) const {
    if (index >= conditions_2D.size()) {
        throw std::out_of_range("Index exceeds the number of available boundary conditions");
    }
    return conditions_2D[index](x, y);
}


